/*
 * UAE - The Un*x Amiga Emulator
 *
 * Save/restore emulator state
 *
 * (c) 1999-2001 Toni Wilen
 */

/* functions to save byte,word or long word
 * independent of CPU's endianess */

#pragma once

extern void save_store_pos_func(byte**);
extern void save_store_size_func(byte**);
extern void restore_store_pos_func(byte**);
extern void restore_store_size_func(byte**);

#define save_store_pos() save_store_pos_func(&dst)
#define save_store_size() save_store_size_func(&dst)
#define restore_store_pos() restore_store_pos_func(&src)
#define restore_store_size() restore_store_size_func(&src)

extern void save_u64_func(byte * *, ulong64);
extern void save_u32_func(byte * *, uint);
extern void save_u16_func(byte * *, ushort);
extern void save_u8_func(byte * *, byte);

extern ulong64 restore_u64_func(byte**);
extern uint restore_u32_func(byte**);
extern ushort restore_u16_func(byte**);
extern byte restore_u8_func(byte**);

extern void save_string_func(byte**, const TCHAR*);
extern TCHAR* restore_string_func(byte**);

#define SAVESTATE_PATH 0
#define SAVESTATE_PATH_FLOPPY 1
#define SAVESTATE_PATH_VDIR 2
#define SAVESTATE_PATH_HDF 3
#define SAVESTATE_PATH_HD 4
#define SAVESTATE_PATH_CD 5

extern void save_path_func(byte**, const TCHAR*, int type);
extern TCHAR* restore_path_func(byte**, int type);

#define save_u64(x) save_u64_func(&dst, (x))
#define save_u32(x) save_u32_func(&dst, (x))
#define save_u16(x) save_u16_func(&dst, (x))
#define save_u8(x) save_u8_func(&dst, (x))

#define restore_u64() restore_u64_func(&src)
#define restore_u32() restore_u32_func(&src)
#define restore_u16() restore_u16_func(&src)
#define restore_u8() restore_u8_func(&src)

#define save_string(x) save_string_func(&dst, (x))
#define restore_string() restore_string_func(&src)

#define save_path(x, p) save_path_func(&dst, (x), p)
#define restore_path(p) restore_path_func(&src, p)

/* save, restore and initialize routines for Amiga's subsystems */

extern byte* restore_cpu(byte*);
extern void restore_cpu_finish();
extern byte* save_cpu(int*, byte*);
extern byte* restore_cpu_extra(byte*);
extern byte* save_cpu_extra(int*, byte*);
extern byte* save_cpu_trace(int*, byte*);
extern byte* restore_cpu_trace(byte*);

extern byte* restore_mmu(byte*);
extern byte* save_mmu(int*, byte*);

extern byte* restore_fpu(byte*);
extern byte* save_fpu(int*, byte*);

extern byte* restore_disk(int, byte*);
extern byte* save_disk(int, int*, byte*, bool);
extern byte* restore_floppy(byte* src);
extern byte* save_floppy(int* len, byte*);
extern byte* save_disk2(int num, int* len, byte* dstptr);
extern byte* restore_disk2(int num, byte* src);
extern void DISK_save_custom(uint* pdskpt, ushort* pdsklen, ushort* pdsksync, ushort* pdskbytr);
extern void DISK_restore_custom(uint pdskpt, ushort pdsklength, ushort pdskbytr);
extern void restore_disk_finish();

extern byte* restore_custom(byte*);
extern byte* save_custom(int*, byte*, int);
extern byte* restore_custom_extra(byte*);
extern byte* save_custom_extra(int*, byte*);

extern byte* restore_custom_sprite(int num, byte* src);
extern byte* save_custom_sprite(int num, int* len, byte*);

extern byte* restore_custom_agacolors(byte* src);
extern byte* save_custom_agacolors(int* len, byte*);

extern byte* restore_custom_event_delay(byte* src);
extern byte* save_custom_event_delay(int* len, byte* dstptr);

extern byte* restore_blitter(byte* src);
extern byte* save_blitter(int* len, byte*);
extern byte* restore_blitter_new(byte* src);
extern byte* save_blitter_new(int* len, byte*);
extern void restore_blitter_finish();

extern byte* restore_audio(int, byte*);
extern byte* save_audio(int, int*, byte*);
extern void restore_audio_finish();

extern byte* restore_cia(int, byte*);
extern byte* save_cia(int, int*, byte*);
extern void restore_cia_finish();

extern byte* restore_expansion(byte*);
extern byte* save_expansion(int*, byte*);

extern byte* restore_p96(byte*);
extern byte* save_p96(int*, byte*);
extern void restore_p96_finish();

extern byte* restore_keyboard(byte*);
extern byte* save_keyboard(int*, byte*);

extern byte* restore_akiko(byte* src);
extern byte* save_akiko(int* len, byte*);
extern void restore_akiko_finish();

extern byte* restore_cdtv(byte* src);
extern byte* save_cdtv(int* len, byte*);
extern void restore_cdtv_finish();

extern byte* restore_dmac(byte* src);
extern byte* save_dmac(int* len, byte*);

extern byte* restore_filesys(byte* src);
extern byte* save_filesys(int num, int* len);
extern byte* restore_filesys_common(byte* src);
extern byte* save_filesys_common(int* len);
extern int save_filesys_cando();

extern byte* restore_gayle(byte* src);
extern byte* save_gayle(int* len, byte*);
extern byte* restore_ide(byte* src);
extern byte* save_ide(int num, int* len, byte*);

extern byte* save_cd(int num, int* len);
extern byte* restore_cd(int, byte* src);
extern void restore_cd_finish();

extern byte* save_configuration(int* len);
extern byte* restore_configuration(byte* src);
extern byte* save_log(int, int* len);
extern byte* restore_log(byte* src);

extern byte* restore_input(byte* src);
extern byte* save_input(int* len, byte* dstptr);

extern byte* restore_inputstate(byte* src);
extern byte* save_inputstate(int* len, byte* dstptr);
extern void clear_inputstate();

extern byte* save_a2065(int* len, byte* dstptr);
extern byte* restore_a2065(byte* src);
extern void restore_a2065_finish();

extern byte* restore_debug_memwatch(byte* src);
extern byte* save_debug_memwatch(int* len, byte* dstptr);
extern void restore_debug_memwatch_finish();

extern byte* save_cycles(int* len, byte* dstptr);
extern byte* restore_cycles(byte* src);

extern void restore_cram(int, size_t);
extern void restore_sram(int, size_t);
extern void restore_fram(int, size_t);
extern void restore_zram(int, size_t);
extern void restore_bootrom(int, size_t);
extern void restore_pram(int, size_t);
extern void restore_a3000lram(int, size_t);
extern void restore_a3000hram(int, size_t);

extern void restore_ram(size_t, byte*);

extern byte* save_cram(int*);
extern byte* save_sram(int*);
extern byte* save_fram(int*);
extern byte* save_zram(int*);
extern byte* save_bootrom(int*);
extern byte* save_pram(int*);
extern byte* save_a3000lram(int*);
extern byte* save_a3000hram(int*);

extern byte* restore_rom(byte*);
extern byte* save_rom(int, int*, byte*);

extern byte* restore_action_replay(byte*);
extern byte* save_action_replay(int*, byte*);
extern byte* restore_hrtmon(byte*);
extern byte* save_hrtmon(int*, byte*);

extern void savestate_initsave(const TCHAR* filename, int docompress, int nodialogs, bool save);
extern int save_state(const TCHAR* filename, const TCHAR* description);
extern void restore_state(const TCHAR* filename);
extern void savestate_restore_finish();
extern void savestate_memorysave();

extern void custom_save_state();
extern void custom_prepare_savestate();

extern bool savestate_check();

#define STATE_SAVE 1
#define STATE_RESTORE 2
#define STATE_DOSAVE 4
#define STATE_DORESTORE 8
#define STATE_REWIND 16
#define STATE_DOREWIND 32

extern int savestate_state;
extern TCHAR savestate_fname[MAX_DPATH];
extern struct zfile* savestate_file;

static __forceinline bool isrestore()
{
    return savestate_state == STATE_RESTORE || savestate_state == STATE_REWIND;
}

extern void savestate_quick(int slot, int save);

extern void savestate_capture(int);
extern void savestate_free();
extern void savestate_init();
extern void savestate_rewind();
extern int savestate_dorewind(int);
extern void savestate_listrewind();
extern void statefile_save_recording(const TCHAR*);
extern void savestate_capture_request();